/*
 * bw_Sqlite.cpp
 *
 *  Created on: 2018年9月5日
 *  Author: Degang.Wu (windragon@126.com)
 *  Desc:
 */

#include <bw_Sqlite.h>
#include "bw_FcgiRequest.h"

using namespace std;

namespace bwcgi {

BWCursor::BWCursor(BWRow& row) {
	if (!row.empty()) {
		for (auto it = row.begin(); it != row.end(); it++) {
			this->cursor.push_back(it->second);
		}
	}
	this->row = row;
}

BWCursor::~BWCursor() {

}

int BWCursor::getInt(int idx) {
	if (idx >= 0 && idx < (int) cursor.size()) {
		return atoi(cursor[idx].c_str());
	}

	return -1;
}

int BWCursor::getInt(const char* key) {
	if (row.find(key) != row.end()) {
		return atoi(row[key].c_str());
	}

	return -1;
}

S64 BWCursor::getInt64(int idx) {
	if (idx >= 0 && idx < (int) cursor.size()) {
		return atoll(cursor[idx].c_str());
	}

	return -1;
}

S64 BWCursor::getInt64(const char* key) {
	if (row.find(key) != row.end()) {
		return atoll(row[key].c_str());
	}

	return -1;
}

std::string BWCursor::getString(int idx) {
	if (idx >= 0 && idx < (int) cursor.size()) {
		return (cursor[idx]);
	}
	return "";
}

std::string BWCursor::getString(const char* key) {
	if (row.find(key) != row.end()) {
		return (row[key]);
	}

	return "";
}

BWSqlite::BWSqlite(const char* dbfile) :
		sDbfile(dbfile), pDb(NULL) {
	// TODO Auto-generated constructor stub
	int ret = sqlite3_open(sDbfile.c_str(), &pDb);
	if (SQLITE_OK != ret) {
		cgi_debug("open db failed:%s", sqlite3_errmsg(pDb));
		sqlite3_close(pDb);
		pDb = NULL;
	}
}

BWSqlite::~BWSqlite() {
	// TODO Auto-generated destructor stub
	if (pDb) {
		sqlite3_close(pDb);
		pDb = NULL;
	}
}

BWRows BWSqlite::QeuryRows(const char* sql) {
	BWRows bwrows;
	if (!pDb) {
		return bwrows;
	}
	cgi_debug("query rows cmd:%s", sql);

	char *zErrMsg = NULL;
	char **azResult = NULL; //二维数组存放结果
	int nrow = 0;
	int ncolumn = 0;

	sqlite3_get_table(pDb, sql, &azResult, &nrow, &ncolumn, &zErrMsg);
	if (zErrMsg) {
		cgi_debug("%s", zErrMsg);
		sqlite3_free(zErrMsg);
	}

	for (int i = 1; i < (nrow + 1); i++) {
		BWRow row;
		for (int j = 0; j < ncolumn; j++) {
			if(azResult[i * ncolumn + j]!=NULL){
				row[azResult[j]] = azResult[i * ncolumn + j];
			}
		}
		if (!row.empty()) {
			bwrows.push_back(row);
		}
	}

	if (azResult) {
		sqlite3_free_table(azResult);
	}
	return bwrows;
}

BWRow BWSqlite::QueryRow(const char* sql) {
	BWRow row;
	if (!FCGI_file_exist(sDbfile.c_str())) {
		return row;
	}

	//限定最多只查一条记录
	std::string sqlLimit(sql);
	std::transform(sqlLimit.begin(), sqlLimit.end(), sqlLimit.begin(),
			::tolower);

	if (sqlLimit.find("limit") == std::string::npos) {
		sqlLimit.append(" LIMIT 1 ");
	}

	cgi_debug("query row cmd:%s", sqlLimit.c_str());
	char *zErrMsg = NULL;
	char **azResult = NULL; //二维数组存放结果
	int nrow = 0;
	int ncolumn = 0;

	sqlite3_get_table(pDb, sql, &azResult, &nrow, &ncolumn, &zErrMsg);
	if (zErrMsg) {
		cgi_debug("%s", zErrMsg);
		sqlite3_free(zErrMsg);
	}

	for (int i = 1; i < (nrow + 1); i++) {
		for (int j = 0; j < ncolumn; j++) {
			if(azResult[i * ncolumn + j]!=NULL){
				row[azResult[j]] = azResult[i * ncolumn + j];
			}
		}
		if (!row.empty()) {
			break;
		}
	}

	if (azResult) {
		sqlite3_free_table(azResult);
	}

	return row;
}

int BWSqlite::Exec(const char* sql) {
	int ret = 0;
	char *zErrMsg = NULL;
	cgi_debug("cmd:%s", sql);
	ret = sqlite3_exec(pDb, sql, NULL, NULL, &zErrMsg);
	cgi_debug("exec ret=%d", ret);
	if (zErrMsg) {
		cgi_debug("%s", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	return ret;
}

int BWSqlite::Insert(const char* sql) {
	return Exec(sql);
}

int BWSqlite::Delete(const char* sql) {
	return Exec(sql);
}

int BWSqlite::Update(const char* sql) {

	return Exec(sql);
}

bool BWSqlite::ExistTable(BWSqlite* pDb, const char* tb) {
	if (!pDb) {
		return false;
	}
	//SELECT count(*) FROM sqlite_master WHERE type='table' AND name='config'
	char sql[SZ_1K];
	snprintf(sql, sizeof(sql),
			"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='%s'",
			tb);
	BWRow row = pDb->QueryRow(sql);
	BWCursor cursor(row);
	int count = cursor.getInt(0);

	return count != 0;
}

bool BWSqlite::ExistTable(const char* dbfile, const char *tb) {
	if (!FCGI_file_exist(dbfile)) {
		return false;
	}

	BWSqlite db(dbfile);

	return ExistTable(&db, tb);
}

// 返回插入数据的id
int BWSqlite::Inserted_id(const char* table_name) {
	char sql[SZ_1K] = { 0 };
	snprintf(sql, sizeof(sql), "select last_insert_rowid() as rid from %s",
			table_name);
	BWRow rowid_row = QueryRow(sql);
	if (rowid_row.empty()) {
		cgi_debug("get inserted id error,table:%s", table_name);
		return -1;
	}
	std::string rid = rowid_row["rid"];

	snprintf(sql, sizeof(sql), "select id from %s where rowid=%s", table_name,
			rid.c_str());
	BWRow id_row = QueryRow(sql);
	if (id_row.empty()) {
		cgi_debug("get id error,table:%s,rowid:%s", table_name, rid.c_str());
		return -1;
	}
	std::string id = id_row["id"];
	return atoi(id.c_str());
}

} /* namespace bwcgi */
